﻿const tedious = require('tedious');
const SQLTypes = tedious.TYPES;
const config = {
    userName: 'admin',
    password: 'admin',
    server: 'localhost',
    options: {
        database: 'MsgGateway'
    }
};

//接收数据的类型，是数组还是对象
const AssemblyType = { CLASS: 'cls', ARRAY: 'arr' }


function runSp(name, paras, assembly = AssemblyType.CLASS) {
    return new Promise(function (resolve, reject) {
        const cn = new tedious.Connection(config);
        cn.on('connect', cnErr => {
            if (cnErr) {
                reject(cnErr);
                return
            }

            const dataset = [];
            let headers = [], rowset = [];

            // create request to execute direct command text or stored procedure
            const req = new tedious.Request(name, function (reqErr) {
                if (reqErr) reject(reqErr);
                else resolve(dataset);
                cn.close();
            })

            // set parameter values
            paras && paras.forEach(p => req.addParameter(p.name, p.type, p.value));

            // update row headers
            req.on('columnMetadata', columns => {
                headers = [...columns.map(c => c.colName)];
                rowset = []
            });

            // determine row assemblers
            let rowAssembler, rowsetAssembler;
            if (assembly === AssemblyType.CLASS) {
                rowAssembler = columns => rowset.push(headers.reduce((obj, cn, idx) => ({ ...obj, [cn]: columns[idx].value }), {}));
                rowsetAssembler = () => dataset.push(rowset)
            } else {
                rowAssembler = columns => rowset.push(columns.map(c => c.value));
                rowsetAssembler = () => dataset.push({ headers, rowset })
            }

            // accept row
            req.on('row', rowAssembler);

            // accept rowset
            req.on('doneInProc', rowsetAssembler);

            // run stored procedure
            cn.callProcedure(req);
        })
    })
}

module.exports = {
    AssemblyType,
    runSp
}
